home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_074 / less / signal.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  4KB  |  211 lines

  1. /*
  2.  * Routines dealing with signals.
  3.  *
  4.  * A signal usually merely causes a bit to be set in the "signals" word.
  5.  * At some convenient time, the mainline code checks to see if any
  6.  * signals need processing by calling psignal().
  7.  * An exception is made if we are reading from the keyboard when the
  8.  * signal is received.  Some operating systems will simply call the
  9.  * signal handler and NOT return from the read (with EINTR).
  10.  * To handle this case, we service the interrupt directly from
  11.  * the handler if we are reading from the keyboard.
  12.  */
  13.  
  14. #include "less.h"
  15. #ifndef amiga
  16. #include <signal.h>
  17. #endif
  18. #include <setjmp.h>
  19.  
  20. /*
  21.  * The type of signal handler functions.
  22.  * Usually int, although it should be void.
  23.  */
  24. typedef int             HANDLER;
  25.  
  26. /*
  27.  * "sigs" contains bits indicating signals which need to be processed.
  28.  */
  29. public int sigs;
  30. #define S_INTERRUPT     01
  31. #ifdef SIGTSTP
  32. #define S_STOP          02
  33. #endif
  34.  
  35. extern int reading;
  36. extern char *first_cmd;
  37. extern jmp_buf main_loop;
  38.  
  39. /*
  40.  * Interrupt signal handler.
  41.  */
  42.     static HANDLER
  43. interrupt()
  44. {
  45. #ifdef amiga
  46.     printf("interrupt\n");
  47. #else
  48.     SIGNAL(SIGINT, interrupt);
  49.     sigs |= S_INTERRUPT;
  50.     if (reading)
  51.         psignals();
  52. #endif
  53. }
  54.  
  55. #ifdef SIGTSTP
  56. /*
  57.  * "Stop" (^Z) signal handler.
  58.  */
  59.     static HANDLER
  60. stop()
  61. {
  62.     SIGNAL(SIGTSTP, stop);
  63.     sigs |= S_STOP;
  64.     if (reading)
  65.         psignals();
  66. }
  67. #endif
  68.  
  69. /*
  70.  * Set up the signal handlers.
  71.  */
  72.     public void
  73. init_signals()
  74. {
  75. #ifdef amiga
  76. #else
  77.     (void) SIGNAL(SIGINT, interrupt);
  78. #ifdef SIGTSTP
  79.     (void) SIGNAL(SIGTSTP, stop);
  80. #endif
  81. #endif
  82. }
  83.  
  84. /*
  85.  * Process any signals we have recieved.
  86.  * A received signal cause a bit to be set in "sigs".
  87.  */
  88.     public void 
  89. psignals()
  90. `{
  91. #ifdef amiga
  92. #else
  93.     register int tsignals;
  94.  
  95.     tsignals = sigs;
  96.     sigs = 0;
  97.     if (tsignals == 0)
  98.         return;
  99.  
  100.     dropout();              /* Discard any buffered output */
  101.  
  102. #ifdef SIGTSTP
  103.     if (tsignals & S_STOP)
  104.     {
  105.         /*
  106.          * Clean up the terminal.
  107.          */
  108. #ifdef SIGTTOU
  109.         SIGNAL(SIGTTOU, SIG_IGN);
  110. #endif
  111.         lower_left();
  112.         clear_eol();
  113.         flush();
  114.         raw_mode(0);
  115. #ifdef SIGTTOU
  116.         SIGNAL(SIGTTOU, SIG_DFL);
  117. #endif
  118.         SIGNAL(SIGTSTP, SIG_DFL);
  119. #if SIGSETMASK
  120.         /*
  121.          * This system will not allow us to send a 
  122.          * stop signal (SIGTSTP) to ourself
  123.          * while we are in the signal handler, like maybe now.
  124.          * (This can be the case if we are reading; see comment above.)
  125.          * So we ask the silly system for permission to do so.
  126.          */
  127.         sigsetmask(0);
  128. #endif
  129.         kill(getpid(), SIGTSTP);
  130.         /*
  131.          * ... Bye bye. ...
  132.          * Hopefully we'll be back later and resume here...
  133.          * Reset the terminal and arrange to repaint the
  134.          * screen when we get back to the main command loop.
  135.          */
  136.         SIGNAL(SIGTSTP, stop);
  137.         raw_mode(1);
  138.         first_cmd = "r";
  139.         longjmp(main_loop, 1);
  140.     }
  141. #endif
  142.     if (tsignals & S_INTERRUPT)
  143.     {
  144.         bell();
  145.         /*
  146.          * {{ You may wish to replace the bell() with 
  147.          *    error("Interrupt"); }}
  148.          */
  149.     }
  150.     longjmp(main_loop, 1);
  151. #endif
  152. }
  153.  
  154. /*
  155.  * Pass the specified command to a shell to be executed.
  156.  * Like plain "system()", but handles resetting terminal modes, etc.
  157.  */
  158.     public void
  159. lsystem(cmd)
  160.     char *cmd;
  161. {
  162.     int inp;
  163.  
  164.     /*
  165.      * Print the command which is to be executed.
  166.      */
  167.     lower_left();
  168.     clear_eol();
  169.     puts("!");
  170.     puts(cmd);
  171.     puts("\n");
  172.  
  173. #ifdef amiga
  174.     Execute(cmd, 0L, 0L);
  175. #else
  176.     /*
  177.      * De-initialize the terminal and take out of raw mode.
  178.      */
  179.     deinit();
  180.     flush();
  181.     raw_mode(0);
  182.  
  183.     /*
  184.      * Restore signals to their defaults.
  185.      */
  186.     SIGNAL(SIGINT, SIG_DFL);
  187. #ifdef SIGTSTP
  188.     SIGNAL(SIGTSTP, SIG_DFL);
  189. #endif
  190.     /*
  191.      * Pass the command to the system to be executed.
  192.      */
  193.     inp = dup(0);
  194.     close(0);
  195.     open("/dev/tty", 0);
  196.  
  197.     system(cmd);
  198.  
  199.     close(0);
  200.     dup(inp);
  201.     close(inp);
  202.  
  203.     /*
  204.      * Reset signals, raw mode, etc.
  205.      */
  206.     init_signals();
  207.     raw_mode(1);
  208.     init();
  209. #endif
  210. }
  211.